package de.digisalt.dsnesds.editors.projectmeta.operations;

import java.util.HashSet;
import java.util.Iterator;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.IUndoContext;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;

public abstract class AbstractUndoableOperation implements IUndoableOperation
{
	private final String								msg;
	public final Object									newValue;
	public final Object									model;
	private final HashSet<IUndoContext>	undoContexts	= new HashSet<IUndoContext>();

	/**
	 * The standard constructor
	 * 
	 * @param msg The String to be displayed in the UI when the user wants to undo/redo the operation
	 * @param model the model object to process the command on
	 * @param newValue the new value from the GUI to be set
	 */
	public AbstractUndoableOperation(String msg, Object model, Object newValue)
	{
		this.msg = msg;
		this.model = model;
		this.newValue = newValue;
		initVariables();
	}

	/*
	 * This method should be overwritten by implementing classes. The idea is to
	 * temporarily store all orgininal model information before the command has
	 * been executed so it can be rewritten to the model once the UNDO method is
	 * executed
	 */
	public abstract void initVariables();

	@Override
	public void addContext(IUndoContext context)
	{
		this.undoContexts.add(context);
	}

	@Override
	public boolean canExecute()
	{
		return true;
	}

	@Override
	public boolean canRedo()
	{
		return true;
	}

	@Override
	public boolean canUndo()
	{
		return true;
	}

	@Override
	public void dispose()
	{
		// TODO Auto-generated method stub

	}

	@Override
	public abstract IStatus execute(IProgressMonitor monitor, IAdaptable info)
			throws ExecutionException;

	@Override
	public IUndoContext[] getContexts()
	{
		int s = undoContexts.size();
		IUndoContext[] contexts = new IUndoContext[s];
		Iterator<IUndoContext> iterator = undoContexts.iterator();
		for (int i = 0; i < s; i++)
		{
			contexts[i] = iterator.next();
		}
		return contexts;
	}

	@Override
	public String getLabel()
	{
		return msg;
	}

	@Override
	public boolean hasContext(IUndoContext context)
	{
		if (undoContexts.size() > 0)
		{
			return true;
		}
		return false;
	}

	@Override
	public abstract IStatus redo(IProgressMonitor monitor, IAdaptable info)
			throws ExecutionException;

	@Override
	public void removeContext(IUndoContext context)
	{
		// TODO Auto-generated method stub

	}

	@Override
	public abstract IStatus undo(IProgressMonitor monitor, IAdaptable info)
			throws ExecutionException;

}
